﻿
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;



enum Gan {
	干,甲,乙,丙,丁,戊,己,庚,辛,壬,癸
};

enum Zhi {
	支,子,丑,寅,卯,辰,巳,午,未,申,酉,戌,亥
};

enum OrganRating {
	虚症,平,实症
};

enum OrganName {
	器,肾,肝,肺,心,脾,膀胱,胆,大肠,小肠,胃
};


//////////////易得病症/////////////////

const char * EtgIll[11][3] = {
	
	{"\0","\0","\0"},
	{"腰疼  阳痿、早泄  早泄遗精  女人性冷淡  阴部四周湿痒  不孕  早衰  白发脱发  痔疮  干咳  骨质增生  股骨头坏死  易骨折  脊髓炎  手脚凉  前列腺炎、增生  阴肿  身材矮小  耳鸣耳聋  中耳炎  耳穿孔  老想躺着  精力不足  皮肤干燥  尿毒症  肾虚腰痛、滑精、遗精、下肢萎软、健忘、气喘尿频、尿急、多尿遗忘、五更泄、早衰\0",
	"无\0",
	"手脚发热  不孕  脱发  掉牙早  骨质增生  下肢水肿  耳鸣耳聋早  中耳炎  耳穿孔  记忆力差  易怒  心衰  易引起多汗盗汗  易引发咳嗽多痰  阴部湿痒  前列腺炎、肾结石、尿闭、淋漓不尽\0"},
	{"血压低贫血 晕车呕吐  多泪  易伤筋 （例如：腰脱、韧带拉伤、肩周炎、关节炎、腱鞘炎、网球肘、乒乓球肘、踝关节拉伤）  帕金森症  近视弱视  斜视  乙肝  脂肪肝  酒精肝  脑梗  性急易怒  瘫痪  眩晕、目花、四肢麻木、关节不利、筋挛拘急、抽搐麻痹、下肢瘫痪、头手颤抖、黄疸型肝炎、贫血\0",
	"无\0",
	"脑梗  偏头痛  易伤筋（例如：腰脱、韧带拉伤、肩周炎、关节炎、腱鞘炎、网球肘、乒乓球肘、踝关节拉伤）  帕金森症  近视弱视  白内障  青光眼  玻璃体浑浊  斜视  性急易怒  瘫痪  抽筋  颠顶痛、乳房痛、两肋痛、小腹痛\0"
	},
	{"易感冒  咳嗽多痰  水肿  鼻炎咽炎  易在面部出现斑痘  易患牛皮癣、白癜风、银屑病、风疹、痒疹、疱疹  老年时打呼噜  心衰  皱纹多  气短、声哑、失音、肺炎、矽肺、各种皮肤病、疹病\0",
	"无\0",
	"哮喘  水肿  气短  鼻塞  中青年就出现打呼噜  肺气肿 水肿  肺癌  干咳、咳血、胸闷疼痛、痰中带血、口燥咽干、鼻息肉、头肿\0"},
	{"心动过缓心衰、心律不齐（心跳慢） 昏迷  血压低贫血  心悸胆怯  心慌  精神病颠狂症  精神抑郁症  记忆力差健忘  多汗盗汗  口吃  说话慢  失眠  心梗  健忘智力低下、痴呆、癔症、自汗、手心多汗、面色无华、心衰\0",
	"无\0",
	"心脉过强，心率快  高血压  癫狂症  记忆力差健忘  少汗无汗  口吃  说话慢  脑血栓  脑出血  瘫痪或是半身不遂  失眠  心梗、紫癜、静脉曲张、嬉笑不休、爪甲紫暗\0"},
	{"糖尿病  疲劳症  肌肉萎缩无弹性  消化能力差  流口水  面黄肌瘦  易患面瘫嘴歪  腿疼肌肉疼  肌肉瘤粉瘤  食少、便溏泄泻、痢疾、黄疸、肢倦疲乏、脱肛、内脏下垂、子宫下垂、中气下陷、不能升举、急性胃肠炎、口歪、唇角发炎、崩漏\0",
	"无\0",
	"血糖高  易患出血症（脑出血、鼻出血、胃出血、尿血、便血）  大便每天二次以上不成条  肌肉僵硬  肥胖（四肢粗。脖子粗、脸胖）  易患面瘫嘴歪  易流口水  唇紫  食欲旺  腿疼肌肉疼  肌肉瘤粉瘤  腹满胀痛、紫癜、经少经闭、水肿\0"},
	{"尿频  儿童易尿床  尿多  易患尿道炎  尿蛋白  尿急遗尿、尿等待\0",
	"无\0",
	"尿急尿少  尿淋漓尿不尽  等尿  尿道炎  尿血  膀胱癌  尿闭\0"},
	{"胆囊炎  易怒  易发热低烧高烧不退  后背右肩胛缘酸疼、口苦\0",
	"无\0",
	"胆结石  胆囊息肉  易怒  易发热低烧高烧不退  头痛\0"},
	{"大便秘结  拉肚子  急性肠炎、泄泻\0",
	"无\0",
	"结肠炎  肠癌  直肠癌  大便秘结\0"},
	{"胃肠炎  女人月经期短月经量少  月经不准  月经走得早  不孕（输卵管堵塞）  月经有血块  盆腔炎  宫颈糜烂  右下腹牵拉痛、子宫附件炎\0",
	"无\0",
	"疝气  阑尾炎  女人子宫肌瘤  女人卵巢囊肿  痛经  月经不准  白带  盆腔炎  月经量多有血块色不正常\0"},
	{"胃疼不胀  烧心  食量小  急性胃肠炎、泄泻、胃溃疡\0",
	"无\0",
	"肥胖尤其肚子大  易呕吐  食欲旺能吃  胃腹胀痛  口中有味  呃逆打嗝  胃癌  腹中痞块\0"}
};





///////////////////////////////////////


struct Organ {

	OrganName name;	//脏器名称

	uint16_t votes =0;//用来存储脏器得分

	OrganRating rating ;

	Organ():name(器),rating(平){}
	

	const char* NumToName() {
		switch (name) 
		{
		case 0:
			return "器";
		case 1:
			return "肾";
		case 2:
			return "肝";
		case 3:
			return "肺";
		case 4:
			return "心";
		case 5:
			return "脾";
		case 6:
			return "膀胱";
		case 7:
			return "胆";
		case 8:
			return "大肠";
		case 9:
			return "小肠";
		case 10:
			return "胃";

		default:
			return 0;
		break;
		}
	}

	const char* VotesToRating() {
		switch (votes)
		{
		case 0:
			return "虚症";
		case 1:
			return "平";
		case 2:
			return "实症";
		case 3:
			return "实症";
		case 4:
			return "实症";
		case 5:
			return "实症";
		case 6:
			return "实症";
		case 7:
			return "实症";
		case 8:
			return "实症";

		default:
			return 0;
			break;
		}
	}
};


struct Patient {

	string name = "";
	//八字算源
	short Yob = NULL;
	short Mob = NULL;
	short Dob = NULL;
	short Hob = NULL;

	short ganInd = 0;
	short zhiInd = 0;

	short szInd = 0;	//四柱序号

	Gan BzGan[4] ;
	Zhi BzZhi[4] ;
	//Bz8 is a result of Bz5 and Bz7

	//十器官
	Organ organ [10];

	Patient(short aYob, short aMob, short aDob, short aHob)
	{
		Yob = aYob;
		Mob = aMob;
		Dob = aDob;
		Hob = aHob;

		//八字初始化
		for (uint16_t i = 0; i < 4; i++)
		{
			BzGan[i] = 干;
			BzZhi[i] = 支;
		}
		
		organ[0].name = 肾;
		organ[1].name = 肝;
		organ[2].name = 肺;
		organ[3].name = 心;
		organ[4].name = 脾;
		organ[5].name = 膀胱;
		organ[6].name = 胆;
		organ[7].name = 大肠;
		organ[8].name = 小肠;
		organ[9].name = 胃;

		GetEights(Yob, Mob, Dob, Hob);
		VoteforOrgans();
		RateOrgans();
	}

	//用八字序号确定八字
	void CalcGanZhi(short szInd) {
		switch (ganInd)
		{
		case 0:
			BzGan[szInd] = 癸;
			break;
		case 1:
			BzGan[szInd] = 甲;
			break;
		case 2:
			BzGan[szInd] = 乙;
			break;
		case 3:
			BzGan[szInd] = 丙;
			break;
		case 4:
			BzGan[szInd] = 丁;
			break;
		case 5:
			BzGan[szInd] = 戊;
			break;
		case 6:
			BzGan[szInd] = 己;
			break;
		case 7:
			BzGan[szInd] = 庚;
			break;
		case 8:
			BzGan[szInd] = 辛;
			break;
		case 9:
			BzGan[szInd] = 壬;
			break;
		case 10:
			BzGan[szInd] = 癸;
			break;
		default:
			BzGan[szInd] = 干;
			break;
		}

		switch (zhiInd)
		{
		case 0:
			BzZhi[szInd] = 亥;
			break;
		case 1:
			BzZhi[szInd] = 子;
			break;
		case 2:
			BzZhi[szInd] = 丑;
			break;
		case 3:
			BzZhi[szInd] = 寅;
			break;
		case 4:
			BzZhi[szInd] = 卯;
			break;
		case 5:
			BzZhi[szInd] = 辰;
			break;
		case 6:
			BzZhi[szInd] = 巳;
			break;
		case 7:
			BzZhi[szInd] = 午;
			break;
		case 8:
			BzZhi[szInd] = 未;
			break;
		case 9:
			BzZhi[szInd] = 申;
			break;
		case 10:
			BzZhi[szInd] = 酉;
			break;
		case 11:
			BzZhi[szInd] = 戌;
			break;
		case 12:
			BzZhi[szInd] = 亥;
			break;
		default:
			BzZhi[szInd] = 支;
			break;
		}
	}

	//算出八字
	void GetEights(short aYob, short aMob, short aDob, short aHob) {
		
		//年份
		szInd = 0;	//第一个四柱
		ganInd = (aYob - 3) % 10;		//年干
		zhiInd = (aYob - 3) % 12;		//年支

		CalcGanZhi(szInd);	

		//月份
		szInd = 1;	//第二个四柱
		(aMob + 1 >= 11) ? zhiInd = aMob - 11 : zhiInd = aMob + 1;					//月支
		ganInd = (BzGan[0]%5*2+1+aMob-2)%10;		//月干

		CalcGanZhi(szInd);

		//日
		szInd = 2;	//第三个四柱
		int g, c, y,	z,i;
		if (aMob <= 2)
			aMob += 12;
		c = aYob / 100;
		y = aYob % 100;
		g = 4 * c + c / 4 + 5 * y + y / 4 + 3 * (aMob + 1) / 5 + aDob - 3;
		ganInd = g % 10;

		aMob % 2?i = 6:i = 0;
		z = 8 * c + c / 4 + 5 * y + y / 4 + 3 * (aMob + 1) / 5 + aDob + 7 + i;
		zhiInd = z % 12 + 6;
		if (zhiInd > 7)zhiInd = zhiInd % 12;
		
		CalcGanZhi(szInd);

		//时
		szInd = 3;	//第四个四柱
		ganInd = (BzGan[2] * 2 - 1) + (aHob / 100 + 1) / 2;
		ganInd = ganInd % 10;

		int t,tem=0;
		t = aHob / 100;
		(t >= 1 && t < 23)?(tem = (t = t + 1) / 2 + 1):(tem = 1);
		zhiInd = tem % 12;

		CalcGanZhi(szInd);
	}

	//得到八字后给各个器官打分
	void VoteforOrgans() {
		//四个干
		for (uint16_t i = 0; i < 4; i++)
		{
			switch (BzGan[i])
			{
			case 甲:
				organ[6].votes++;
				break;
			case 乙:
				organ[1].votes++;
				break;
			case 丙:
				organ[8].votes++;
				break;
			case 丁:
				organ[3].votes++;
				break;
			case 戊:
				organ[9].votes++;
				break;
			case 己:
				organ[4].votes++;
				break;
			case 庚:
				organ[7].votes++;
				break;
			case 辛:
				organ[2].votes++;
				break;
			case 壬:
				organ[5].votes++;
				break;
			case 癸:
				organ[0].votes++;
				break;
			default:
				break;
			}
		}

		//四个支
		for (uint16_t i = 0; i < 4; i++)
		{
			switch (BzZhi[i])
			{
			case 子:
				organ[5].votes++;
				break;
			case 丑:
				organ[4].votes++;
				break;
			case 寅:
				organ[6].votes++;
				break;
			case 卯:
				organ[1].votes++;
				break;
			case 辰:
				organ[9].votes++;
				break;
			case 巳:
				organ[3].votes++;
				break;
			case 午:
				organ[8].votes++;
				break;
			case 未:
				organ[4].votes++;
				break;
			case 申:
				organ[7].votes++;
				break;
			case 酉:
				organ[2].votes++;
				break;
			case 戌:
				organ[9].votes++;
				break;
			case 亥:
				organ[0].votes++;
				break;

			default:
				break;
			}
		}
			
	}

	//根据打分确定评级
	void RateOrgans() {
		for (uint16_t i = 0; i < 10; i++) {
			if (organ[i].votes == 1 ) {
				organ[i].rating = 平;
			}else if( organ[i].votes>=2) {
				organ[i].rating = 实症;
			}
			else {
				organ[i].rating = 虚症;
			}
		}
	}

};

std::ostream& operator<<(std::ostream& out, Gan& gan)
{
	switch (gan)
	{
	case 1:
		cout<<"甲";
		break;
	case 2:
		cout << "乙";
		break;
	case 3:
		cout << "丙";
		break;
	case 4:
		cout << "丁";
		break;
	case 5:
		cout << "戊";
		break;
	case 6:
		cout << "己";
		break;
	case 7:
		cout << "庚";
		break;
	case 8:
		cout << "辛";
		break;
	case 9:
		cout << "壬";
		break;
	case 10:
		cout << "癸";
		break;
	default:
		break;
	}

	return out;
}

std::ostream& operator<<(std::ostream& out, Zhi& zhi)
{
	switch (zhi)
	{
	case 1:
		cout << "子";
		break;
	case 2:
		cout << "丑";
		break;
	case 3:
		cout << "寅";
		break;
	case 4:
		cout << "卯";
		break;
	case 5:
		cout << "辰";
		break;
	case 6:
		cout << "巳";
		break;
	case 7:
		cout << "午";
		break;
	case 8:
		cout << "未";
		break;
	case 9:
		cout << "申";
		break;
	case 10:
		cout << "酉";
		break;
	case 11:
		cout << "戌";
		break;
	case 12:
		cout << "亥";
		break;
	default:
		break;
	}
	return out;
}

//类方法里暗含this参数,<<只能有两个参数,故只能在类外定义
std::ostream& operator<<(std::ostream& out, Patient& ptnt)	
{
	//显示八字
	cout << "八字为: ";
	for (uint16_t i = 0; i < 4; i++) {
		cout << ptnt.BzGan[i] << ptnt.BzZhi[i] << "\t";
	}
	cout << endl;
	//显示各脏器分数
	for (uint16_t i = 0; i < 10; i++) {

		if (i != 5 && i != 7 && i != 8) {
			cout << ptnt.organ[i].NumToName() << ":" << ptnt.organ[i].votes << "分" << "\t" << "\t" << "评级:" << ptnt.organ[i].VotesToRating() << endl;
		}
		else {
			cout << ptnt.organ[i].NumToName() << ":" << ptnt.organ[i].votes << "分" <<"\t" << "评级:" << ptnt.organ[i].VotesToRating() << endl;
		}
	}
	//显示易得病症
	cout << "易得病症:" << endl;
	for (uint16_t i = 1; i < 11; i++) {
		cout << ptnt.organ[i-1].NumToName() << "相关： ";
		cout << EtgIll[i][ptnt.organ[i-1].rating] <<"\n"<< endl;
	}
	return out;
}

void ArchivePatient(Patient& ptnt) {
	cout << "是否归档？输入0取消 输入1归档" << endl;
	scanf_s("%d", &ptnt.name);
	//存入文件

}

int main()
{
	bool DontExit = true;
	short bufYob = 0;
	short bufMob = 0;
	short bufDob = 0;
	short bufHob = 0;

	while(DontExit) {
		cout << "目标人物哪年出生？" << endl;
		scanf_s("%d",&bufYob);

		cout << "目标人物几月出生？" << endl;
		scanf_s("%d", &bufMob);

		cout << "目标人物几号出生？" << endl;
		scanf_s("%d", &bufDob);

		cout << "目标人物几点出生(四位数)？" << endl;
		scanf_s("%d", &bufHob);

		 
		Patient* ptt = new Patient(bufYob, bufMob, bufDob, bufHob);	//构造时就算出八字了


		//打印评估结果
		cout << *ptt << endl;

		//归档功能
		bool bArchive;
		
		cout << "是否归档？输入0取消 输入1归档" << endl;
		scanf_s("%d",&bArchive);
		if (bArchive) {
			ArchivePatient(*ptt);
		}

		bufYob = NULL;
		bufMob = NULL;
		bufDob = NULL;
		bufHob = NULL;



		delete ptt;

		cout << "是否退出？输入0退出,输入1继续" << endl;
		cin >> DontExit;
	}
}




/*

	//心得:
		1、计算年八字的时候,生硬造轮子
		//现在-1984
		if (aYob >= 1984) {
			ganInd = ((aYob - 1983) % 60)%10 ;
			zhiInd = ((aYob - 1983) % 60)%12 ;
		}
		else if(aYob>=1924) {//1984-1924
			ganInd = ((aYob - 1923) % 60) % 10;
			zhiInd = ((aYob - 1923) % 60) % 12;
		}
		else if(aYob >= 1864) {//1924-1864
			ganInd = ((aYob - 1863) % 60) % 10;
			zhiInd = ((aYob - 1863) % 60) % 12;
		}
		else {
			cout << "输入无效" << endl;
		}
		在冲动做轮子之前，一定要上网找找现成的轮子！！！

		2、类中类尤其要记得初始化,debug半天得到的教训
			否则莫名其妙访问越界

		3、
*/
